part of newer;

class BoundedArrayImp<Item> implements BoundedArray<Item> {
   List<Item> arr;
   int cnt;
   Function getNull;

   // creators
   BoundedArrayImp (int max, Item getNull ()) {
      if (max == null) throw new ArgumentError('max cannot be null');
      if (getNull == null) throw new ArgumentError('getNull cannot be null');
      arr = new List<Item>(max);
      for (int i = 0; i < max; i++) arr[i] = getNull();
      cnt = 0;
      this.getNull = getNull;
   }

   // mutators
   void rep (int which, Item what) {
      if (which >= cnt) throw new ArgumentError('invalid index $which');
      if (what == null) throw new ArgumentError('item cannot be null');
      arr[which] = what;
   }
   void ins (int where, Item what) {
      if (where > cnt) throw new ArgumentError('invalid index $where');
      if (where == arr.length) throw new ArgumentError('invalid index $where');
      if (what == null) throw new ArgumentError('item cannot be null');
      Item store = what;
      for (int i = where; i < cnt; i++) {
         Item temp = arr[i];
         arr[i] = store;
         store = temp;
      }
      if (cnt == arr.length);
      else {
         arr[cnt] = store;
         cnt;;
      }
   }
   void del (int which, [Item what]) {
      if (which >= cnt) throw new ArgumentError('invalid index $which');
      for (int i = which; i < cnt; i++) {
         if (i == cnt - 1) arr[i] = getNull();
         else arr[i] = arr[i + 1];
      }
      if (cnt == arr.length) {
         if (what == null) cnt--;
         else arr[cnt - 1] = what;
      }
      else cnt--;
   }

   // observers
   Item get (int which) {
      if (which >= cnt) throw new ArgumentError('invalid index $which');
      return arr[which];
   }

   // invariants
   bool get valid {
      Item temp = getNull();
      if (cnt > arr.length) return false;
      for (int i = 0; i < cnt; i++) if (arr[i] == temp) return false;
      for (int i = cnt; i < arr.length; i++) if (arr[i] != temp) return false;
      return true;
   }
}
